/****************************************************************************
** Player project V1.0
** playerimpl.cpp
**
** Copyright (C) 2008 Skander Jabouzi (Skander Software Solutions).
** Contact: skander@skanderjabouzi.com or jabouzi@gmail.com
**
** This file is part of the Player open source software.
**
** GNU General Public License Usage
** This file may be used under the terms of the GNU
** General Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file.  Please review the following information
** to ensure GNU General Public Licensing requirements will be met:
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
** exception, Nokia gives you certain additional rights. These rights
** are described in the Nokia Qt GPL Exception version 1.3, included in
** the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "playerimpl.h"
//
PlayerImpl::PlayerImpl( QWidget * parent, Qt::WFlags f) 
	: QDialog(parent, f)
{
	path = QCoreApplication::applicationDirPath ();
	if (path.data()[path.size() - 1] != '/') path += "/";
	setupUi(this);
	setWindowFlags(Qt::WindowMinimizeButtonHint);
	audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
	mediaObject = new Phonon::MediaObject(this);
	Phonon::createPath(mediaObject, audioOutput);
	videoWidget = new Phonon::VideoWidget(this);
	Phonon::createPath(mediaObject, videoWidget);
	metaInformationResolver = new Phonon::MediaObject(this);
	mediaObject->setTickInterval(1000);   
	QHBoxLayout *videoLayout = new QHBoxLayout;
    videoLayout->addWidget(videoWidget);  
    video.frame->setLayout(videoLayout); 
    //QGridLayout *gridLayout = new QGridLayout;
    //video.setLayout(gridLayout);
	
	setUI();
	setActions();
	timeLabel->installEventFilter(this);
	volumeLabel->installEventFilter(this);
	timeLeft = false;	
	init();
	adjustWindow();
}

void PlayerImpl::init()
{
	index = 0;
	playing = 0;
	stopped = false;
	playButton->setEnabled(false);
	prevButton->setEnabled(false);
	nextButton->setEnabled(false);
	stopButton->setEnabled(false);
	seekNextButton->setEnabled(false);
    seekPrevButton->setEnabled(false);
    reloadButton->setEnabled(false);
	newLoad = true;
}

// adjust window position to center of the screen
void PlayerImpl::adjustWindow()
{
	QDesktopWidget *desktop = QApplication::desktop();
	int screenWidth, width; 
	int screenHeight, height;
	int x, y;
	QSize windowSize;	 
	screenWidth = desktop->width(); 
	screenHeight = desktop->height();
	windowSize = size(); 
	width = windowSize.width(); 
	height = windowSize.height();	
	x = (screenWidth - width) / 2;
	y = (screenHeight - height) / 2;
	y -= 50;	
	move (x, y);
}

void PlayerImpl::closeEvent(QCloseEvent *event)
{
	video.close();
}

// set audio file (media source)
void PlayerImpl::setAudio(QStringList files)
{
	sources.clear();
	for (int i = 0; i < files.size(); i++){
		//Phonon::MediaSource source(string);
		
		Phonon::MediaSource source(files.at(i));
		sources.insert(i,source);
		//qDebug(files.at(i).toLatin1().data());
		metaInformationResolver->setCurrentSource(source);
		qDebug(metaInformationResolver->metaData().value("TITLE").toLatin1().data());
		//qDebug(metaInformationResolver->currentSource().fileName().toLatin1().data());
	}	
	playButton->setEnabled(true);	
	stopButton->setEnabled(true);
	reloadButton->setEnabled(true);
	seekPrevButton->setEnabled(true);
	seekNextButton->setEnabled(true);
	//audioSource = files;
	//for (int i = 0; i < files.size(); i++){
		//Phonon::MediaSource source(files.at(i));
		//qDebug(files.at(i).toLatin1().data());
		//metaInformationResolver->setCurrentSource(source);
		//qDebug(metaInformationResolver->metaData().value("TITLE").toLatin1().data());
		//qDebug(metaInformationResolver->currentSource().fileName().toLatin1().data());
	//}	
}

// set player label text
void PlayerImpl::setLabel()
{
	//QStringList list_ = audioSource.at(index).split("/");
	//QString filename = list_[list_.size()-1];
	//label->setText(filename);
}

// simulate the play button clicked
void PlayerImpl::autoPlay()
{
	playButton->animateClick(10);	
}

// get the audio source file
Phonon::MediaSource PlayerImpl::getAudio()
{
	if (playing == 1)
		index++;			
	if (playing == 2)
		index--;
	if ( sources.size() > 1){
		if (index == 0){
			prevButton->setEnabled(false);
			nextButton->setEnabled(true);    		
		} 
		else if (index > 0 && index < sources.size() - 1){
			prevButton->setEnabled(true);
			nextButton->setEnabled(true);
		}
		else if (index == sources.size() - 1){
			prevButton->setEnabled(true);
			nextButton->setEnabled(false);
		}
	}	
	return sources.at(index);	
	
}

// actions
void PlayerImpl::setActions(){
	connect(playButton, SIGNAL(clicked()), this, SLOT(play()));
	connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
	connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
	connect(prevButton, SIGNAL(clicked()), this, SLOT(prev()));
	connect(addButton, SIGNAL(clicked()), this, SLOT(load()));
	connect(seekNextButton, SIGNAL(clicked()), this, SLOT(seekNext()));	
	connect(seekPrevButton, SIGNAL(clicked()), this, SLOT(seekPrev()));	
	connect(reloadButton, SIGNAL(clicked()), this, SLOT(reload()));	
	connect(videoButton, SIGNAL(clicked()), this, SLOT(showVideo()));	
	connect(mediaObject, SIGNAL(finished()), this, SLOT(finished()));
	connect(audioOutput, SIGNAL(volumeChanged ( qreal )), this, SLOT(setVolume()));
	connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime()));
	connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime()));	
	connect(mediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool)));
	connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged(Phonon::State, Phonon::State)));
	//playAction = new QAction(this);     
    //connect(playAction, SIGNAL(triggered()), this, SLOT(play()));
    //playButton->addAction(playAction);
}

// set the player UI : buttons icons and sliders
void PlayerImpl::setUI(){
	setWindowIcon(QIcon(path+"images/audio.png"));
    //playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
    playButton->setIcon(QIcon(path+"images/play.png"));
    //stopIcon = style()->standardIcon(QStyle::SP_MediaStop);
    stopButton->setIcon(QIcon(path+"images/stop.png"));
    //nextIcon = style()->standardIcon(QStyle::SP_MediaSkipForward);
    nextButton->setIcon(QIcon(path+"images/skipForward.png"));
    //prevIcon = style()->standardIcon(QStyle::SP_MediaSkipBackward);
    prevButton->setIcon(QIcon(path+"images/skipBackward.png"));
    addButton->setIcon(QIcon(path+"images/eject.png"));	
    seekNextButton->setIcon(QIcon(path+"images/seekForward.png"));
    seekPrevButton->setIcon(QIcon(path+"images/seekBackward.png"));
    reloadButton->setIcon(QIcon(path+"images/reload.png"));
    videoButton->setIcon(QIcon(path+"images/video.png"));
    //volumeIcon = style()->standardPixmap(QStyle::SP_MediaVolume);
    //mutedIcon = style()->standardPixmap(QStyle::SP_MediaVolumeMuted);
    volumeLabel->setPixmap(QPixmap::fromImage(QImage(path+"images/volume.png")));
    seekSlider = new Phonon::SeekSlider(this);   
    seekSlider->setMediaObject(mediaObject);    
    QHBoxLayout *seekerLayout = new QHBoxLayout;
    seekerLayout->addWidget(seekSlider);  
    playerFrame->setLayout(seekerLayout);    
    volumeSlider = new Phonon::VolumeSlider(this);   
    volumeSlider->setAudioOutput(audioOutput);
    volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);    
    QHBoxLayout *volumeLayout = new QHBoxLayout;
    volumeLayout->addWidget(volumeSlider);  
    volumeFrame->setLayout(volumeLayout);
}

// play audio file
void PlayerImpl::play()
{   	
	if (mediaObject->state() == Phonon::LoadingState || newLoad){
		newLoad = false;			
		Phonon::MediaSource sourceFile = getAudio();		
		//Phonon::MediaSource source(sourceFile);
		mediaObject->setCurrentSource(sources.at(index));
		label->setText(mediaObject->currentSource().fileName());
		setLabel(); 
		//metaInformationResolver->setCurrentSource(mediaObject->currentSource());
		//qDebug(metaInformationResolver->metaData().value("TITLE").toLatin1().data());
		//metaInformationResolver->setCurrentSource(source);
		mediaObject->play();
		playIcon = style()->standardIcon(QStyle::SP_MediaPause);
		playButton->setIcon(QIcon(path+"images/pause.png"));
	}
	else if( mediaObject->state() == Phonon::StoppedState){
		if (playing > 0)	{
			Phonon::MediaSource sourceFile = getAudio();				
			mediaObject->setCurrentSource(sources.at(index));
			label->setText(mediaObject->currentSource().fileName());	
			setLabel(); 	
			//Phonon::MediaSource source(sourceFile);
			//mediaObject->setCurrentSource(source);			
			//metaInformationResolver->setCurrentSource(source);
		}		
		mediaObject->play();
		playIcon = style()->standardIcon(QStyle::SP_MediaPause);
		playButton->setIcon(QIcon(path+"images/pause.png"));
		//qDebug(mediaObject->metaData().value("TITLE").toLatin1().data());
	}
	else if (mediaObject->state() == Phonon::PlayingState) {				
		mediaObject->pause();           
		playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
		playButton->setIcon(QIcon(path+"images/play.png"));  
	}
	else if (mediaObject->state() == Phonon::PausedState) {
		mediaObject->play();
		playIcon = style()->standardIcon(QStyle::SP_MediaPause);
		playButton->setIcon(QIcon(path+"images/pause.png"));
	}
	else if (mediaObject->state() == Phonon::ErrorState) {	
            QMessageBox::warning(this, "Phonon Mediaplayer", mediaObject->errorString(), QMessageBox::Close);
            if (mediaObject->errorType() == Phonon::FatalError) {
                init();
            } else {
                mediaObject->pause();
            }
     }
}

// show playing time (left or elapsed just click on the label to switch)
void PlayerImpl::updateTime()
{
	QString sign = "";
    long len = mediaObject->totalTime();
    long pos = mediaObject->currentTime();
    if (timeLeft == true) {
    	pos = len -pos;
    	sign = "-";    	
	}
    QString timeString;    
    if (pos || len)
    {
        int sec = pos/1000;
        int min = sec/60;
        int hour = min/60;
        int msec = pos;

        QTime playTime(hour%60, min%60, sec%60, msec%1000);
        sec = len / 1000;
        min = sec / 60;
        hour = min / 60;
        msec = len;

        QTime stopTime(hour%60, min%60, sec%60, msec%1000);
        QString timeFormat = "hh:mm:ss";
        //if (hour > 0)
            //timeFormat = "hh:mm:ss";        
        timeString = playTime.toString(timeFormat);
        if (len)
           sign += timeString;
         //qDebug(QString::number(mediaObject->currentTime()).toLatin1().data());
    }
    timeLabel->setText(sign);
}

// stop playing
void PlayerImpl::stop()
{
	playing = 0;
	mediaObject->stop();
	playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
	playButton->setIcon(QIcon(path+"images/play.png"));
	updateTime();
}

// change the volume
void PlayerImpl::setVolume()
{
	if (audioOutput->volume () == 0.0) volumeLabel->setPixmap(QPixmap::fromImage(QImage(path+"images/mute.png")));
	else volumeLabel->setPixmap(QPixmap::fromImage(QImage(path+"images/volume.png")));
}

// when the audio source is finished
void PlayerImpl::finished(){
	stop();
	if (index < sources.size() - 1)
		next();
}

// switch between time left or elapsed one
void PlayerImpl::changeSign(){	
	timeLeft = !timeLeft;
}

// detect click on the time label
bool PlayerImpl::eventFilter(QObject *o, QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress)
    {
        if (o == timeLabel)
        {
            changeSign();
            return TRUE;
        }
        if (o == volumeLabel)
        {        	
        	if (audioOutput->volume () == 0.0) {
    			audioOutput->setVolume(1.0);
    			volumeLabel->setPixmap(QPixmap::fromImage(QImage(path+"images/volume.png")));
			}
    		else {
    			audioOutput->setVolume(0.0);
    			volumeLabel->setPixmap(QPixmap::fromImage(QImage(path+"images/mute.png"))); 
			}    		     
       	}
    }

    return QWidget::eventFilter(o, e);
}

void PlayerImpl::next()
{
	stop();
	playing = 1;
	mediaObject->play();
}

void PlayerImpl::prev()
{
	stop();
	playing = 2;
	mediaObject->play();
}

void PlayerImpl::load()
{	
	
	QStringList list = QFileDialog::getOpenFileNames(this,tr("Open one or more files"),".",tr("audios (*.mp3 *.wma *.ogg *.wave *.midi *.avi *.mpeg *.mpg *.wmv *.divx)"));
	if (list.size() > 0){
		init();
		setAudio(list);
		mediaObject->play();
	}
}

void PlayerImpl::reload()
{
   	mediaObject->seek(0);
}

void PlayerImpl::seekNext()
{
	mediaObject->seek(mediaObject->currentTime () + 10000);
}

void PlayerImpl::seekPrev()
{
	mediaObject->seek(mediaObject->currentTime () - 10000);
}


void PlayerImpl::hasVideoChanged(bool hasVideo){
	
	if (hasVideo)
		video.show();
	else video.hide();	
}

void PlayerImpl::showVideo()
{
	video.show();
}

void PlayerImpl::stateChanged(Phonon::State newstate, Phonon::State oldstate)
{
	qDebug(QString::number(newstate).toLatin1().data());
	qDebug(QString::number(oldstate).toLatin1().data());	
}
//
